package com.atomos.strategy.emission
{
	import flash.geom.Point;
	
	import com.atomos.log.AtomosDebug;
	import com.atomos.particle.Particle;
	import com.bourre.error.ClassCastException;
	import com.bourre.error.NullPointerException;
	import com.bourre.error.UnimplementedVirtualMethodException;
	import com.bourre.log.PixlibStringifier;
	import com.bourre.utils.ClassUtils;	

	public class AbstractEmission implements EmissionStrategy
	{
		protected var _oParticleType : Class;
		protected var _pEmissionPosition : Point;
		
		/**
		 * 
		 * @param type
		 * @param position
		 * @throws com.bourre.error.ClassCastException
		 * @throws com.bourre.error.NullPointerException
		 * @throws com.bourre.error.UnimplementedVirtualMethodException
		 */
		public function AbstractEmission ( type : Class, position : Point = null )
		{
			_checkVirtualMethods ();			
			setParticleType( type );
			setPosition ( position );
		}
		
		public function isFinish():Boolean
		{
			return true;
		}
		
		public function prepareEmission( time : Number ) : void	
		{}
		
		public function hasNext() : Boolean
		{
			return false;
		}
		
		public function nextTime():Number
		{
			return 0;
		}
		
		public function remove():void 
		{}
		
		public function next() : *
		{
			var p : Particle = new _oParticleType() as Particle; 
			p.position = _pEmissionPosition.clone();
	
			return p;
		}
		
		public function getPosition() : Point
		{
			return _pEmissionPosition;
		}
		
		public function setPosition( pos : Point ) : void
		{
			_pEmissionPosition = pos != null ? pos : new Point();
		}
		
		public function getParticleType() : Class
		{
			return _oParticleType;
		}
		
		public function setParticleType( type : Class ) : void
		{
			_checkParticleType( type );
			_oParticleType = type;
		}
		
		public function toString () : String
		{
			return PixlibStringifier.stringify( this );
		}
		
		/*-----------------------------------------------------------------------
			PROTECTED METHODS
		------------------------------------------------------------------------*/
		
		protected function _checkParticleType ( c : Class ) : void
		{
			if( c == null )
			{				
				AtomosDebug.ERROR( "Particle's class passed to " + this + " is null" );
				
				throw new NullPointerException ( "Particle's class passed to " + this + " is null" );
			}
			else if( ( new c () as Particle ) == null )
			{
				AtomosDebug.ERROR( "Particle's class passed to " + this + 
								   " is not a subclass of the com.atomos.particle::Particle class : " + 
								   new c() );
				
				throw new ClassCastException ( "Particle's class passed to " + this + 
											   " is not a subclass of the com.atomos.particle::Particle class : " + 
											   new c() );
			}
		}
		
		protected function _checkVirtualMethods () : void
		{
			if( !ClassUtils.isImplementedAll( this,
											  "com.atomos.strategy.emission::AbstractEmission",
											  "isFinish",
											  "hasNext" ) )
			{
				AtomosDebug.ERROR( this + " don't implements one of these virtual methods from '" + 
										  "com.atomos.strategy.emission::AbstractEmission' : " +
										  "isFinish, prepareEmission, hasNext" );
				
				throw new UnimplementedVirtualMethodException ( 
										  this + " don't implements one of these virtual methods from '" + 
										  "com.atomos.strategy.emission::AbstractEmission' : " +
										  "isFinish, prepareEmission, haNext"  );
			}
		}
	}
}